<template>
  <div class="app-container">
    <el-form v-show="showSearch" ref="queryRef" :model="queryParams" :inline="true">
      <el-form-item label="数据源名称" prop="name">
        <el-input
          v-model="queryParams.name"
          placeholder="请输入数据源名称"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="数据库类型" prop="dataSourceType">
        <el-select
          v-model="queryParams.dataSourceType"
          placeholder="请选择数据库类型"
          clearable
          @change="handleQuery"
        >
          <el-option
            v-for="item in dataSourceTypeOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="Plus"
          @click="handleAdd"
          v-hasPermi="['web:db:datasource:dbDatasource:add']"
        >
          新增
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          icon="Edit"
          :disabled="single"
          @click="handleUpdate({})"
          v-hasPermi="['web:db:datasource:dbDatasource:edit']"
        >
          修改
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="Delete"
          :disabled="multiple"
          @click="handleDelete({})"
          v-hasPermi="['web:db:datasource:dbDatasource:remove']"
        >
          删除
        </el-button>
      </el-col>
      <right-toolbar v-model:showSearch="showSearch" @query-table="getList" />
    </el-row>

    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="数据源名称" align="center" prop="name" />
      <el-table-column label="编码" align="center" prop="code" />
      <el-table-column label="数据库类型" align="center" prop="dataSourceType" />
      <el-table-column label="JDBC链接" align="center" prop="jdbcUrl" show-overflow-tooltip />
      <el-table-column label="数据库用户名" align="center" prop="username" />
      <el-table-column label="连接池初始大小" align="center" prop="initialSize" />
      <el-table-column label="描述" align="center" prop="remark" />
      <el-table-column label="操作" align="center" width="240">
        <template #default="scope">
          <el-button
            link
            type="primary"
            icon="Edit"
            @click="handleUpdate(scope.row)"
            v-hasPermi="['web:db:datasource:dbDatasource:edit']"
          >
            修改
          </el-button>
          <el-button
            link
            type="primary"
            icon="Key"
            style="color: orange"
            @click="handleUpdatePassword(scope.row)"
            v-hasPermi="['web:db:datasource:dbDatasource:editPass']"
          >
            修改密码
          </el-button>
          <el-button
            link
            type="primary"
            icon="Delete"
            style="color: red"
            @click="handleDelete(scope.row)"
            v-hasPermi="['web:db:datasource:dbDatasource:remove']"
          >
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination
      v-show="total > 0"
      :total="total"
      v-model:page="pageParams.pageNum"
      v-model:limit="pageParams.pageSize"
      @pagination="getList"
    />

    <el-dialog
      :title="title"
      v-model="open"
      width="700px"
      append-to-body
      :close-on-press-escape="false"
      :close-on-click-modal="false"
    >
      <el-form ref="formRef" :model="form" :rules="rules" label-width="130px">
        <el-form-item label="数据源名称" prop="name">
          <el-input v-model="form.name" placeholder="请输入数据源名称" />
        </el-form-item>
        <el-form-item label="编码" prop="code">
          <el-input v-model.trim="form.code" placeholder="请输入编码" />
        </el-form-item>
        <el-form-item label="JDBC链接" prop="jdbcUrl">
          <el-input v-model="form.jdbcUrl" type="textarea" placeholder="请输入JDBC链接" />
        </el-form-item>
        <el-form-item label="数据库用户名" prop="username">
          <el-input v-model="form.username" placeholder="请输入数据库用户名" />
        </el-form-item>
        <el-form-item v-if="!form.id" label="数据库密码" prop="password">
          <el-input v-model="form.password" placeholder="请输入数据库密码" show-password />
        </el-form-item>
        <el-form-item label="数据库类型" prop="dataSourceType">
          <el-select
            v-model="form.dataSourceType"
            placeholder="请选择数据库类型"
            @change="handleDataSourceTypeChange"
          >
            <el-option
              v-for="item in dataSourceTypeOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="schema" prop="schema">
          <el-input v-model="form.schema" placeholder="请输入schema" />
        </el-form-item>
        <el-form-item label="描述" prop="remark">
          <el-input v-model="form.remark" placeholder="请输入描述" />
        </el-form-item>

        <el-divider class="!my-10">
          <el-link type="primary" @click="advancedShow = !advancedShow"> 高级配置 </el-link>
        </el-divider>
        <div v-show="advancedShow">
          <el-form-item label="连接池初始大小" prop="initialSize">
            <el-input v-model="form.initialSize" placeholder="请输入连接池初始大小" />
          </el-form-item>
          <el-form-item label="连接池最小连接数" prop="minIdle">
            <el-input v-model="form.minIdle" placeholder="请输入连接池最小连接数" />
          </el-form-item>
          <el-form-item label="连接池最大连接数" prop="maxActive">
            <el-input v-model="form.maxActive" placeholder="请输入连接池最大连接数" />
          </el-form-item>
          <el-form-item label="获取连接超时时间" prop="maxWait">
            <el-input v-model="form.maxWait" placeholder="请输入获取连接超时时间">
              <template #append> ms </template>
            </el-input>
          </el-form-item>
          <el-form-item label="空闲检测时间间隔" prop="timeBetweenEvictionRuns">
            <el-input v-model="form.timeBetweenEvictionRuns" placeholder="请输入空闲检测时间间隔">
              <template #append> ms </template>
            </el-input>
          </el-form-item>
          <el-form-item label="连接最小生存时间" prop="minEvictableIdleTime">
            <el-input v-model="form.minEvictableIdleTime" placeholder="请输入连接最小生存时间">
              <template #append> ms </template>
            </el-input>
          </el-form-item>
          <el-form-item label="连接最大生存时间" prop="maxEvictableIdleTime">
            <el-input v-model="form.maxEvictableIdleTime" placeholder="请输入连接最大生存时间">
              <template #append> ms </template>
            </el-input>
          </el-form-item>
          <el-form-item label="空闲时检测" prop="testWhileIdle">
            <el-radio-group v-model="form.testWhileIdle">
              <el-radio :value="true" label="是" />
              <el-radio :value="false" label="否" />
            </el-radio-group>
          </el-form-item>
          <el-form-item label="获取时检测" prop="testOnBorrow">
            <el-radio-group v-model="form.testOnBorrow">
              <el-radio :value="true" label="是" />
              <el-radio :value="false" label="否" />
            </el-radio-group>
          </el-form-item>
          <el-form-item label="用完时检测" prop="testOnReturn">
            <el-radio-group v-model="form.testOnReturn">
              <el-radio :value="true" label="是" />
              <el-radio :value="false" label="否" />
            </el-radio-group>
          </el-form-item>
        </div>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="success" :loading="loadingConn" @click="checkConn">检查连接</el-button>
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="Datasource">
  import { ref } from 'vue';
  import {
    isCodeUnion,
    pageDbDatasource,
    editPassword,
    testConnection,
    getDbDatasourceInfo,
    addDbDatasource,
    updateDbDatasource,
    delDbDatasource,
    getDataSourceTypes,
  } from '@/api/web/db/datasource';
  import modal from '@/plugins/modal';

  const queryRef = ref(null);
  const pageParams = ref({
    pageNum: 1,
    pageSize: 10,
  });
  const queryParams = ref({
    name: null,
    dataSourceType: null,
  });
  const list = ref([]);
  const open = ref(false);
  const loading = ref(false);
  const showSearch = ref(true);
  const ids = ref([]);
  const single = ref(true);
  const multiple = ref(true);
  const total = ref(0);
  const title = ref('');

  const formRef = ref(null);
  const form = ref({});
  const rules = ref({
    name: [
      {
        required: true,
        min: 0,
        max: 64,
        message: '名称长度必须介于 0 和 64 之间',
        trigger: 'blur',
      },
    ],
    code: [
      {
        required: true,
        min: 0,
        max: 64,
        message: '编码长度必须介于 0 和 64 之间',
        trigger: 'blur',
      },
      { validator: checkDbCode, trigger: 'change' },
    ],
    schema: [
      {
        required: true,
        min: 0,
        max: 64,
        message: 'schema长度必须介于 0 和 64 之间',
        trigger: 'blur',
      },
    ],
    dataSourceType: [
      {
        required: true,
        min: 0,
        max: 255,
        message: '类型长度必须介于 0 和 255 之间',
        trigger: 'change',
      },
    ],
    jdbcUrl: [
      {
        required: true,
        min: 0,
        max: 1024,
        message: 'jdbc链接长度必须介于 0 和 1024 之间',
        trigger: 'blur',
      },
    ],
    username: [
      {
        required: true,
        min: 0,
        max: 255,
        message: '用户名长度必须介于 0 和 255 之间',
        trigger: 'blur',
      },
    ],
    password: [
      {
        required: true,
        min: 0,
        max: 1000,
        message: '密码长度必须介于 0 和 1000 之间',
        trigger: 'blur',
      },
    ],
    remark: [{ min: 0, max: 255, message: '描述长度必须介于 0 和 255 之间', trigger: 'blur' }],
  });

  const dataSourceTypeOptions = ref([]);
  const advancedShow = ref(false);
  const loadingConn = ref(false);

  function getList() {
    loading.value = true;
    pageDbDatasource(pageParams.value, queryParams.value)
      .then((res) => {
        list.value = res?.data?.records ?? [];
        total.value = res?.data?.total ?? 0;
      })
      .finally(() => {
        loading.value = false;
      });
  }

  function cancel() {
    open.value = false;
    reset();
  }

  function reset() {
    form.value = {
      id: null,
      name: null,
      code: null,
      schema: null,
      dataSourceType: null,
      jdbcUrl: null,
      username: null,
      password: null,
      driverClassName: null,
      initialSize: null,
      minIdle: null,
      maxActive: null,
      maxWait: null,
      timeBetweenEvictionRuns: null,
      minEvictableIdleTime: null,
      maxEvictableIdleTime: null,
      validationQuery: null,
      testWhileIdle: null,
      testOnBorrow: null,
      testOnReturn: null,
      createTime: null,
      createBy: null,
      updateTime: null,
      updateBy: null,
      remark: null,
      userId: null,
      deptId: null,
    };
    formRef.value?.resetFields();
    advancedShow.value = false;
  }

  function handleQuery() {
    pageParams.value.pageNum = 1;
    getList();
  }

  function resetQuery() {
    queryRef.value?.resetFields();
    handleQuery();
  }

  function handleSelectionChange(selection) {
    ids.value = selection.map((item) => item.id);
    single.value = selection.length !== 1;
    multiple.value = !selection.length;
  }

  function initDefaultValue() {
    form.value.testOnBorrow = false;
    form.value.testOnReturn = true;
    form.value.testWhileIdle = true;
    form.value.initialSize = 5;
    form.value.minIdle = 5;
    form.value.maxActive = 200;
    form.value.maxWait = 60000;
    form.value.timeBetweenEvictionRuns = 60000;
    form.value.minEvictableIdleTime = 300000;
    form.value.maxEvictableIdleTime = 900000;
  }

  function handleAdd() {
    reset();
    initDefaultValue();
    title.value = '新增数据源';
    open.value = true;
  }

  function handleUpdate(row) {
    reset();
    const _id = row?.id ?? ids.value?.[0];
    getDbDatasourceInfo(_id).then((res) => {
      form.value = res.data;
      title.value = '修改数据源';
      open.value = true;
    });
  }

  function submitForm() {
    formRef.value.validate((valid) => {
      if (valid) {
        if (form.value.id) {
          updateDbDatasource(form.value).then(() => {
            modal.msgSuccess('修改成功');
            open.value = false;
            getList();
          });
        } else {
          addDbDatasource(form.value).then(() => {
            modal.msgSuccess('新增成功');
            open.value = false;
            getList();
          });
        }
      }
    });
  }

  function handleDelete(row) {
    const _ids = row?.id ?? ids.value.join(',');
    modal
      .confirm('是否确认删除编号为"' + _ids + '"的数据项？')
      .then(() => {
        return delDbDatasource(_ids);
      })
      .then(() => {
        getList();
        modal.msgSuccess('删除成功');
      })
      .catch(() => {});
  }

  function handleUpdatePassword(row) {
    modal
      .prompt('请输入"' + row.name + '"的新密码', '提示', {
        inputType: 'password',
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        closeOnClickModal: false,
      })
      .then(({ value }) => {
        const params = {
          id: row.id,
          password: value,
        };
        editPassword(params).then(() => {
          modal.msgSuccess('修改成功，新密码是：' + value);
        });
      })
      .catch(() => {});
  }

  function checkDbCode(_, value, callback) {
    if (value) {
      isCodeUnion({
        id: form.value.id,
        code: form.value.code,
      }).then((res) => {
        if (res.data) {
          callback(new Error('编码已存在'));
        } else {
          callback();
        }
      });
    } else {
      callback(new Error('请输入编码'));
    }
  }

  function getDataType() {
    getDataSourceTypes().then((res) => {
      dataSourceTypeOptions.value = res.data;
    });
  }

  function handleDataSourceTypeChange(val) {
    dataSourceTypeOptions.value.forEach((item) => {
      if (val === item.value) {
        form.value.driverClassName = item.driverClassName;
        form.value.validationQuery = item.validationQuery;
        if (form.value.dataSourceType === 'mysql') {
          rules.value.schema.forEach((item) => {
            item.required = false;
          });
        } else if (form.value.dataSourceType === 'oracle' || form.value.dataSourceType === 'dm8') {
          rules.value.schema.forEach((item) => {
            item.required = true;
          });
        }
      }
    });
  }

  function checkConn() {
    loadingConn.value = true;
    testConnection(form.value)
      .then((res) => {
        if (res.data) {
          modal.msgSuccess('连接成功');
        } else {
          modal.msgError('连接失败');
        }
      })
      .finally(() => {
        loadingConn.value = false;
      });
  }

  getDataType();
  getList();
</script>
